package com.study.tool;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.module.SimpleModule;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import org.apache.commons.lang3.StringUtils;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 *
 * @author Tony
 * @since 20210130
 */
@SuppressWarnings({"squid:S1996"})
public class JsonTool {

	public static String toJson(Object target) {
		return toJson(target, null);
	}

    /**
     * @param dateFormat "yyyy-MM-dd HH:mm:ss"
     * @return string
     */
    public static String toJson(Object target,String dateFormat) {
        return toJson(target, dateFormat,true);
    }

    /**
     * @param dateFormat "yyyy-MM-dd HH:mm:ss"
     * @return string
     */
    public static String toJson(Object target,String dateFormat,boolean includeNotNull) {
        ObjectMapper mapper = new ObjectMapper();
        if (!StringUtils.isEmpty(dateFormat)) {
            mapper.setDateFormat(new SimpleDateFormat(dateFormat));
        }

        if (includeNotNull){
            mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        }

        mapper.configure(JsonGenerator.Feature.IGNORE_UNKNOWN,true);
        mapper.configure(JsonParser.Feature.ALLOW_MISSING_VALUES,true);
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);
        mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES,true);//大小写脱敏 默认为false  需要改为true
        // 全局日期反序列化配置
        SimpleModule module = new SimpleModule();
        module.addDeserializer(Date.class, new DateDeserializer());
        mapper.registerModule(module);

        try {
            return mapper.writeValueAsString(target);
        } catch (JsonProcessingException e) {
            LogTool.error(JsonTool.class, e);
        } catch (Exception e) {
            LogTool.error(JsonTool.class, e);
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    public static <T> T toObject(String json, Class<?> clazz) {
        return toObject(json, clazz, null);
    }
    
    /**
     * @author Tony Xi
     * @since 20210730
     */
    @SuppressWarnings("unchecked")
    public static <T> T toObjectWithTclass(String json, Class<?> clazz, Class tclazz) {
        return toObject(json, clazz, null, tclazz);
    }

    @SuppressWarnings("unchecked")
    public static <T> T toObject(String json, Class<?> clazz, String dateFormat, Class tclazz) {
        if (StringUtils.isEmpty(json)){
            return null;
        }

        ObjectMapper mapper = new ObjectMapper();
        if (!StringUtils.isEmpty(dateFormat)) {
            mapper.setDateFormat(new SimpleDateFormat(dateFormat));
        }

        mapper.configure(JsonGenerator.Feature.IGNORE_UNKNOWN,true);
        mapper.configure(JsonParser.Feature.ALLOW_MISSING_VALUES,true);
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);
        mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES,true);//大小写脱敏 默认为false  需要改为true
        // 全局日期反序列化配置
        SimpleModule module = new SimpleModule();
        module.addDeserializer(Date.class, new DateDeserializer());
        mapper.registerModule(module);

        JavaType javaType = mapper.getTypeFactory().constructParametricType(clazz, tclazz);

        try {
            return (T) mapper.readValue(json, javaType);
        } catch (Exception e) {
            LogTool.error(JsonTool.class, e);
        }
        return null;
    }

    /**
     * @param json
     * @param clazz
     * @param dateFormat "yyyy-MM-dd HH:mm:ss"
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T toObject(String json, Class<?> clazz,String dateFormat) {
        if (StringUtils.isEmpty(json)){
            return null;
        }

        ObjectMapper mapper = new ObjectMapper();
        if (!StringUtils.isEmpty(dateFormat)) {
            mapper.setDateFormat(new SimpleDateFormat(dateFormat));
        }

        mapper.configure(JsonGenerator.Feature.IGNORE_UNKNOWN,true);
        mapper.configure(JsonParser.Feature.ALLOW_MISSING_VALUES,true);
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);
        mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES,true);//大小写脱敏 默认为false  需要改为true
        // 全局日期反序列化配置
        SimpleModule module = new SimpleModule();
        module.addDeserializer(Date.class, new DateDeserializer());
        mapper.registerModule(module);

        try {
            return (T) mapper.readValue(json, clazz);
        } catch (Exception e) {
            LogTool.error(JsonTool.class, e);
        }
        return null;
    }

	public static JsonNode readValue(String json, String nodeName) throws JsonProcessingException, IOException{
		ObjectMapper objectMapper = new ObjectMapper();
		JsonNode rootNode = objectMapper.readTree(json);
		return rootNode.path(nodeName);
	}

	public static void main(String[] args) throws Exception {
//        Employee.EmployeeBuilder builder = new Employee.EmployeeBuilder();
//        builder.id(100).name("张三").build();
//		Employee employee = builder.build();
//
//        System.out.println("=== builder ===");
//        System.out.println(builder.toString());
//
//        System.out.println("=== test01 ===");
//        String json = JsonTool.toJson(builder.build());
//        System.out.println(json);
//
//        System.out.println("=== test02 ===");
//        json = JsonTool.toJson(builder.build(), null,false);
//        System.out.println(json);
//
//        System.out.println("=== test03 ===");
//        builder.birth(DtTool.convertStringToDate(DtTool.DATE_MASK,"2010-10-05"));
//        json = JsonTool.toJson(builder.build(), DtTool.DATE_MASK,true);// yyyy-MM-dd HH:mm:ss
//        System.out.println(json);

		// =============================================================================
		Employee employee = new Employee()
				.setName("张三")
				.setAddress("北京")
				.setBirth(DtTool.convertStringToDate(DtTool.DATE_MASK, "2000-10-08"));

		Boss boss = new Boss()
				.setAddress("大曹县")
				.setName("boss")
				.setEmployee(employee);
		employee.setBoss(boss);

		System.out.println(JsonTool.toJson(boss, DtTool.DATE_MASK));
		System.out.println(JsonTool.toJson(employee, DtTool.DATE_MASK));
	}
}

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Accessors(chain = true)
class Employee{
	private long id;
	private String name;
	private String address;
	private Date birth;
	@JsonIgnore
	private Boss boss;
}

@Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
class Boss{
	private long id;
	private String name;
	private String address;
	private Date birth;
	private Employee employee;
}
